WICONF.loading = {
    duration: 500,// 动画最短持续时间，避免闪屏，单位 ms
    content: ''
    //fInRender: $.noop// function({content}) 绘制加载容器内容的函数
};
(function(){
    var nStartTime = -1,// 记录开始时间（1970 年 1 月 1 日至今的毫秒数）
        timerLoading,// 避免闪屏的定时器
        aLoadingKey = [],// 储存所有key的顺序，show的时候添加，hide的时候删除对应key
        aLoadingNokey = [],// 储存没有传key的顺序，show的时候添加，hide的时候删除对应key
        oLoadingIn = {};// 储存key和对应显示内容sIn，show的时候添加，remove时候清空
    /**
     * @widoc $.showLoading
     * @namespace aux
     * @des 显示 loading 动画。<span class="t_red">注意：$.showLoading() 和 $.hideLoading() 应该成对使用。</span>
     * 显示说明：多次使用 showloading，显示第一次的内容，当第一次的 loading 被 hide 时，显示下一个未被 hide 的 loading 的内容；开启相同 key 值的 loading 将会被忽略;
     * 关闭说明：若传入的 key 值不存在，则不操作；若不传，则优先关闭第一个未传 key 值的 loading，无未传 key 值的 loading，则不操作。
     * 组件配置，在使用组件前调用：
     <pre class="des-conf"> $.setWiConf('loading',{
    duration:500,// 动画最短持续时间，避免闪屏
    content: ''
    //fInRender: $.noop// function({content}) 绘制加载容器内容的函数
 });</pre>
     * @type function
     * @param {object} opts 配置
     * @param {string} opts.key 每个 loading 唯一的 key 值<span class="t_gray80">，为支持旧版本，此字段允许省略，但将无法控制 hide 时的顺序，不推荐省略</span>。
     * @param {string=} opts.content 文本内容
     * @param {function=} opts.fInRender 加载内容绘制函数，返回值：{string}，function(obj)
     *  - obj.content 初始化时传入的 opts.content
     * @return {object} obj 返回对象
     * @rtn {string} obj.key 返回当前 loading 的 key 值
     */
    $.showLoading = function(opts){
        var conf = WICONF.loading, api;
        var jqLoading = $('body>.loadingdata');
        opts = $.extend({
            //key: ,// 没有传入key，默认储存当前时间戳
            content: conf.content,// 配置项
            fInRender: conf.fInRender// function({content}) 绘制加载容器内容的函数
        }, opts);
        var fInit = function(){
            var fInRender = opts.fInRender,
                sKey = opts.key || $.generateGuid('key'),// 记录当前key值，没有生成唯一键
                sIn;// 显示内容
            if(aLoadingKey.indexOf(sKey) > -1){// key重复 忽略不处理
                return false;
            }
            !opts.key && aLoadingNokey.push(sKey);// 没有传key,将key值存在aLoadingNokey
            aLoadingKey.push(sKey);// key储存在aLoadingKey中 记录顺序
            sIn = fInRender ?
                fInRender({// 根据用户绘制函数绘制内容
                    content: opts.content
                }) :
            '<div class="loadingdata-in">' + opts.content + '</div>';
            oLoadingIn[sKey] = sIn;// 将内容储存在oLoadingIn
            // 若aLoadingIn只有一项，则需要更新显示内容
            if(aLoadingKey.length == 1){
                // 若aLoadingIn只有一项，且无定时器，则为第一次showloading，显示loading动画
                if(!timerLoading){
                    jqLoading = $('<div class="loadingdata">' + sIn + '</div>');
                    $('body').append(jqLoading);
                    nStartTime = new Date().getTime();// 返回 1970 年 1 月 1 日至今的毫秒数。
                }
                else{// 若aLoadingIn只有一项，且有定时器，则仅需更新显示内容
                    clearTimeout(timerLoading);// 清除防闪屏定时器
                    timerLoading = null;
                    jqLoading.html(sIn);
                }
            }
            api.key = sKey;
        };
        api = {
            //key: sKey// 在 fInit() 中赋值，未传 opts.key 时需要在组件中生成
        };
        fInit();
        return api;
    };
    /**
     * @widoc $.hideLoading
     * @namespace aux
     * @des 隐藏 loading 动画。详情参考 $.showLoading()
     * @type function
     * @param {object} opts 配置
     * @param {string} opts.key 每个 loading 唯一的 key 值，与 $.showLoading() 时传入的 key 对应<span class="t_gray80">，为支持旧版本，此字段允许省略，但将无法控制 hide 时的顺序，不推荐省略</span>。
     */
    $.hideLoading = function(opts){
        var jqLoading = $('body>.loadingdata');
        opts = $.extend({
            //key:// 删除对应的key 如果没有key 则删除第一个（最早显示的）未定义key的项
        }, opts);
        var sKey,// 要删除的key
            nKey,// sKey在aLoadingKey中的序号
            nDiff;// 当前距离最早结束时间剩余的毫秒数
        // 要删除的key判断顺序 传入的key > 未传key数组第一项
        sKey = opts.key || aLoadingNokey[0];
        nKey = aLoadingKey.indexOf(sKey);
        if(nKey == -1){// 如果传入的key不存在 则不操作
            return false;
        }
        var fRemove = function(){
            timerLoading = null;
            nStartTime = -1;// 将开始时间归零
            jqLoading.remove();
            oLoadingIn = {};// 清空储存的显示内容sIn
        };
        var fUpdata = function(){
            var nNoKey = aLoadingNokey.indexOf(sKey);
            // 删除对应的key
            aLoadingKey.splice(nKey, 1);
            if(nNoKey !== -1){
                aLoadingNokey.splice(nNoKey, 1);
            }
            if(nKey == 0 && aLoadingKey[0]){// 若删除的为当前显示项（第一项），则更新dom显示内容 如果无显示内容（最后一项被hide） 则不修改
                jqLoading.html(oLoadingIn[aLoadingKey[0]]);
            }
        };
        fUpdata();// 更新数据和显示内容
        if(aLoadingKey.length == 0){// 所有loading都已hide，则删除loading
            if(nStartTime > -1){// 记录了开始时间
                nDiff = nStartTime + WICONF.loading.duration - new Date().getTime();
                if(nDiff <= 0){// 已经超过最早结束时间
                    fRemove();
                }
                else{
                    timerLoading = setTimeout(fRemove, nDiff);
                }
            }
            else{
                fRemove();
            }
        }
    };
})();